import { Upload, Modal } from "antd";
import { Icon } from "@/components/Icon";
import { useMessage } from "@/hooks/web/useMessage";
// import { createImgPreview } from "@/components/Preview/index";
import { useEffect, useMemo, useRef, useState } from "react";
import { store } from "@/redux";

const accessToken = store.getState().user.accessToken;
const uploadUrl = import.meta.env.VITE_API_URL + "/infra/file/upload";

interface UploadPropsType {
	value?: string | any[];
	text?: string;
	fileType: string;
	uploadUrl?: string;
	// 这个属性用于控制文件上传的业务路径
	bizPath?: string;
	// 是否返回url。true：仅返回url  false：返回fileName filePath fileSize
	returnUrl?: boolean;
	// 最大上传数量
	maxCount: number;
	buttonOpen?: boolean;
	multiple?: boolean;
	// 是否显示左右移动按钮
	mover?: boolean;
	// 是否显示下载按钮
	download?: boolean;
	// 删除时是否显示确认框
	removeConfirm?: boolean;
	beforeUpload?: Fn;
	disabled?: boolean;
	onChange?: Fn;
}

const UploadPropsDefault = {
	text: "上传",
	fileType: "all",
	uploadUrl: uploadUrl,
	bizPath: "temp",
	returnUrl: true,
	maxCount: 0,
	buttonOpen: true,
	multiple: true,
	mover: true,
	download: true,
	removeConfirm: false,
	disabled: false
};

const FileUpload = (props: UploadPropsType) => {
	// fix React18 "defaultProps" problem
	props = Object.assign({}, { ...UploadPropsDefault, ...props });

	const { createMessage, createConfirm } = useMessage();
	const prefixCls = "upload";
	const headers = {
		Authorization: `Bearer ${accessToken}`,
		"tenant-id": "1"
	};
	const [fileList, setFileList] = useState<any[]>([]);
	const fileListRef = useRef<any[]>([]);
	const uploadGoOn = useRef<boolean>(true);
	// refs
	const containerRef = useRef(null);
	// preview
	const [previewVisible, setPreviewVisible] = useState<boolean>(false);
	const previewImage = useRef("");
	// 是否达到了最大上传数量
	const isMaxCount = useMemo(() => props.maxCount > 0 && fileList.length >= props.maxCount, [fileList]);

	// 当前是否是上传图片模式
	const isImageMode = useMemo(() => props.fileType === "image", [props.fileType]);
	// 合并 props 和 attrs
	const bindProps = useMemo(() => {
		const bind: any = Object.assign({}, props);
		bind.name = "file";
		bind.listType = isImageMode ? "picture-card" : "text";
		bind.className = [bind.className, { "upload-disabled": props.disabled }];
		bind.data = { biz: props.bizPath, ...bind.data };
		if (!bind.beforeUpload) bind.beforeUpload = onBeforeUpload;
		// 如果当前是图片上传模式，就只能上传图片
		if (isImageMode && !bind.accept) bind.accept = "image/*";
		delete bind.value;
		return bind;
	}, [props]);

	useEffect(() => {
		if (Array.isArray(props.value)) {
			if (props.returnUrl) parsePathsValue(props.value.join(","));
			else parseArrayValue(props.value);
		} else {
			parsePathsValue(props.value);
		}
	}, [props.value]);

	const updateFileList = (val: any) => {
		setFileList(val || []);
		fileListRef.current = val || [];
	};

	// 解析数据库存储的逗号分割
	function parsePathsValue(paths: string) {
		if (!paths || paths.length === 0) {
			updateFileList([]);
			return;
		}
		const list: any[] = [];
		for (const item of paths.split(",")) {
			list.push({
				uid: uidGenerator(),
				name: getFileName(item),
				status: "done",
				url: item,
				response: { status: "history", data: item }
			});
		}
		updateFileList(list);
	}

	// 解析数组值
	function parseArrayValue(array: any[]) {
		if (!array || array.length === 0) {
			updateFileList([]);
			return;
		}
		const list: any[] = [];
		for (const item of array) {
			list.push({
				uid: uidGenerator(),
				name: item.fileName,
				url: item.filePath,
				status: "done",
				response: { status: "history", data: item.filePath }
			});
		}
		updateFileList(list);
	}

	// 文件上传之前的操作
	function onBeforeUpload(file) {
		uploadGoOn.current = true;
		if (isImageMode) {
			if (!file.type.includes("image")) {
				createMessage.warning("请上传图片");
				uploadGoOn.current = false;
				return false;
			}
		}
		// 扩展 beforeUpload 验证
		if (typeof props.beforeUpload === "function") return props.beforeUpload(file);

		return true;
	}

	// 删除处理事件
	function onRemove() {
		if (props.removeConfirm) {
			return new Promise(resolve => {
				createConfirm({
					title: "删除",
					content: `确定要删除这${isImageMode ? "张图片" : "个文件"}吗？`,
					iconType: "warning",
					onOk: () => resolve(true),
					onCancel: () => resolve(false)
				});
			});
		}
		return true;
	}

	// upload组件change事件
	function onFileChange(info: any) {
		if (!info.file.status && uploadGoOn.current === false) info.fileList.pop();

		let fileListTemp = info.fileList;
		// 限制最大上传数
		if (props.maxCount > 0) {
			const count = fileListTemp.length;
			if (count >= props.maxCount) {
				const diffNum = props.maxCount - fileListTemp.length;
				if (diffNum >= 0) fileListTemp = fileListTemp.slice(-props.maxCount);
				else return;
			}
		}
		if (info.file.status === "done") {
			let successFileList = [];
			if (info.file.response.code === 0) {
				successFileList = fileListTemp.map(file => {
					if (file.response) {
						const reUrl = file.response.data;
						file.url = reUrl;
					}
					return file;
				});
			} else {
				successFileList = fileListTemp.filter(item => {
					return item.uid !== info.file.uid;
				});
				createMessage.error(`${info.file.name} 上传失败.`);
			}
			fileListTemp = successFileList;
		} else if (info.file.status === "error") {
			createMessage.error(`${info.file.name} 上传失败.`);
		}
		updateFileList(fileListTemp);
		if (info.file.status === "done" || info.file.status === "removed") {
			// returnUrl为true时仅返回文件路径
			if (props.returnUrl) {
				handlePathChange();
			} else {
				// returnUrl为false时返回文件名称、文件路径及文件大小
				const newFileList: any[] = [];
				for (const item of fileListTemp) {
					if (item.status === "done") {
						const fileJson = {
							fileName: item.name,
							filePath: item.response.data,
							fileSize: item.size
						};
						newFileList.push(fileJson);
					} else {
						return;
					}
				}
				emitValue(newFileList);
			}
		}
	}

	function handlePathChange() {
		const uploadFiles = fileListRef.current;
		let path = "";
		if (!uploadFiles || uploadFiles.length === 0) path = "";

		const pathList: string[] = [];
		for (const item of uploadFiles) {
			if (item.status === "done") pathList.push(item.response.data);
			else return;
		}
		if (pathList.length > 0) path = pathList.join(",");

		emitValue(path);
	}

	// 预览文件、图片
	function onFilePreview(file: any) {
		// if (isImageMode) createImgPreview({ imageList: [file.url], maskClosable: true });
		if (isImageMode) {
			previewImage.current = file.url;
			setPreviewVisible(true);
		} else window.open(file.url);
	}

	function emitValue(value: any) {
		props.onChange && props.onChange(value);
		// emit("change", value);
		// emit("update:value", value);
	}

	function uidGenerator() {
		return `-${Number.parseInt((Math.random() * 10000 + 1, 10).toString())}`;
	}

	function getFileName(path: string) {
		if (path.lastIndexOf("\\") >= 0) {
			const reg = /\\/g;
			path = path.replace(reg, "/");
		}
		return path.substring(path.lastIndexOf("/") + 1);
	}

	return (
		<div ref={containerRef} className={`${prefixCls}-container`}>
			<Upload
				headers={headers}
				multiple={props.multiple}
				action={props.uploadUrl}
				fileList={fileList}
				disabled={props.disabled}
				{...bindProps}
				onRemove={onRemove}
				onChange={onFileChange}
				onPreview={onFilePreview}
			>
				{isImageMode
					? !isMaxCount && (
							<div>
								<Icon icon="ant-design:plus-outlined" />
								<div className="ant-upload-text">{props.text}</div>
							</div>
					  )
					: props.buttonOpen && (
							<a-button disabled={isMaxCount || props.disabled}>
								<Icon icon="ant-design:upload-outlined" />
								<span>{props.text}</span>
							</a-button>
					  )}
			</Upload>
			<Modal open={previewVisible} title="Preview Image" footer={null} onCancel={() => setPreviewVisible(false)}>
				<img alt="example" style={{ height: "500px", width: "100%", objectFit: "cover" }} src={previewImage.current} />
			</Modal>
		</div>
	);
};

export default FileUpload;
